import * as THREE from 'three';
import { createMachine } from 'xstate';
import * as CANNON from 'cannon-es';
import { modelLoader } from '../utils/ModelLoader';

class BaseCharacter extends THREE.Object3D {
    constructor(options = {}) {
        super();
        // 基础属性
        this.stats = {
            health: options.health || 100,
            maxHealth: options.maxHealth || 100,
            stamina: options.stamina || 100,
            maxStamina: options.maxStamina || 100,
            attack: options.attack || 10,
            defense: options.defense || 5,
            speed: options.speed || 5
        };

        // 创建3D对象
        this.mesh = null;
        this.modelUrl = options.modelUrl || '';
        
        // 设置初始变换
        if (options.scale) {
            this.scale.copy(options.scale);
        }
        if (options.position) {
            this.position.copy(options.position);
        }
        if (options.rotation) {
            this.rotation.copy(options.rotation);
        }

        // 动画系统
        this.mixer = null;
        this.animations = new Map();
        this.currentAnimation = null;

        // 物理系统
        this.body = null;
        this.collider = null;
        this.hitboxes = new Map();

        // 状态机
        this.stateMachine = createMachine({
            id: 'character',
            initial: 'idle',
            context: {
                health: this.stats.health,
                stamina: this.stats.stamina,
                isInvincible: false,
                combo: 0
            },
            states: {
                idle: {
                    entry: ['playIdleAnimation'],
                    on: {
                        MOVE: 'moving',
                        ATTACK: 'attacking',
                        DODGE: 'dodging',
                        DAMAGE: 'hit'
                    }
                },
                moving: {
                    entry: ['playMoveAnimation'],
                    on: {
                        STOP: 'idle',
                        ATTACK: 'attacking',
                        DODGE: 'dodging',
                        DAMAGE: 'hit'
                    }
                },
                attacking: {
                    entry: ['playAttackAnimation'],
                    on: {
                        FINISH: 'idle',
                        COMBO: 'attacking',
                        DAMAGE: 'hit'
                    }
                },
                dodging: {
                    entry: ['playDodgeAnimation', 'setInvincible'],
                    exit: ['removeInvincible'],
                    on: {
                        FINISH: 'idle'
                    }
                },
                hit: {
                    entry: ['playHitAnimation', 'takeDamage'],
                    on: {
                        FINISH: 'idle',
                        DEATH: 'dead'
                    }
                },
                dead: {
                    entry: ['playDeathAnimation'],
                    type: 'final'
                }
            }
        });
    }

    // 初始化方法
    async init() {
        await this.loadModel();
        this.setupPhysics();
        this.setupAnimations();
    }

    // 模型加载
    async loadModel() {
        if (!this.modelUrl) return;
        try {
            const { model, animations } = await modelLoader.load(this.modelUrl, {
                scale: this.scale,
                position: this.position,
                rotation: this.rotation
            });
            
            this.mesh = model;
            
            // 存储动画
            animations.forEach((animation, name) => {
                this.animations.set(name, animation);
            });
            
            // 设置动画混合器
            if (this.animations.size > 0) {
                this.mixer = new THREE.AnimationMixer(this.mesh);
            }
            
            return this.mesh;
        } catch (error) {
            console.error('角色模型加载失败:', error);
            throw error;
        }
    }

    // 物理系统设置
    setupPhysics() {
        // 创建物理身体
        const shape = new CANNON.Cylinder(0.5, 0.5, 2, 8);
        this.body = new CANNON.Body({
            mass: 5,
            shape: shape,
            position: new CANNON.Vec3(this.position.x, this.position.y, this.position.z),
            material: new CANNON.Material()
        });

        // 设置阻尼
        this.body.linearDamping = 0.9;
        this.body.angularDamping = 0.9;
    }

    // 动画系统设置
    setupAnimations() {
        if (!this.mesh) return;
        this.mixer = new THREE.AnimationMixer(this.mesh);
    }

    // 更新方法
    update(deltaTime) {
        // 更新动画
        if (this.mixer) {
            this.mixer.update(deltaTime);
        }

        // 更新物理
        if (this.body && this.mesh) {
            this.mesh.position.copy(this.body.position);
            this.mesh.quaternion.copy(this.body.quaternion);
        }

        // 更新状态
        this.updateStats(deltaTime);
    }

    // 更新角色状态
    updateStats(deltaTime) {
        // 恢复体力
        if (this.stats.stamina < this.stats.maxStamina) {
            this.stats.stamina = Math.min(
                this.stats.stamina + 10 * deltaTime,
                this.stats.maxStamina
            );
        }
    }

    // 移动方法
    move(direction) {
        if (!this.body || this.stateMachine.state.value === 'dead') return;

        const force = new CANNON.Vec3(
            direction.x * this.stats.speed,
            0,
            direction.z * this.stats.speed
        );
        this.body.applyForce(force, this.body.position);
    }

    // 攻击方法
    attack() {
        if (this.stats.stamina < 20) return false;
        this.stats.stamina -= 20;
        // TODO: 实现具体攻击逻辑
    }

    // 受伤方法
    takeDamage(amount) {
        const actualDamage = Math.max(1, amount - this.stats.defense);
        this.stats.health = Math.max(0, this.stats.health - actualDamage);

        if (this.stats.health <= 0) {
            this.die();
        }

        return actualDamage;
    }

    // 死亡方法
    die() {
        // TODO: 实现死亡逻辑
    }

    // 清理方法
    dispose() {
        if (this.mixer) {
            this.mixer.stopAllAction();
        }
        if (this.mesh) {
            this.mesh.traverse((child) => {
                if (child.isMesh) {
                    child.geometry.dispose();
                    child.material.dispose();
                }
            });
        }
    }
}

export { BaseCharacter }; 